// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the VECTORMATH_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// VECTORMATH_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef VECTORMATH_EXPORTS
#define VECTORMATH_API __declspec(dllexport)
#else
#define VECTORMATH_API __declspec(dllimport)
#endif

// This class is exported from the VectorMath.dll
class VECTORMATH_API CVectorMath {
public:
	CVectorMath(void);
	// TODO: add your methods here.
};

extern VECTORMATH_API int nVectorMath;

VECTORMATH_API int fnVectorMath(void);

#include <math.h>

#define PI 3.14159265

class VECTORMATH_API Vector3
{
private:
	double x, y, z;
public:
	Vector3(double x=0, double y=0, double z=0)
	{
		this->x = x;
		this->y = y;
		this->z = z;
	}

	void SetX (double newX)
	{
		this->x = newX;
	}

	void SetY (double newY)
	{
		this->y = newY;
	}

	void SetZ (double newZ)
	{
		this->z = newZ;
	}

	double GetX ()
	{
		return this->x;
	}

	double GetY ()
	{
		return this->y;
	}

	double GetZ ()
	{
		return this->z;
	}

	Vector3 operator + (const Vector3 &other)
	{
		return Vector3(this->x + other.x,
			this->y + other.y,
			this->z + other.z);
	}

	Vector3 operator - (const Vector3 &other)
	{
		return Vector3(this->x - other.x,
			this->y - other.y,
			this->z - other.z);
	}

	Vector3 operator * (const double &coef)
	{
		return Vector3(this->x * coef,
			this->y * coef,
			this->z * coef);
	}

	Vector3 operator / (const double &coef)
	{
		return Vector3(this->x / coef,
			this->y / coef,
			this->z / coef);
	}

	double GetLength()
	{
		double xSquared = this->x * this->x,
			ySquared = this->y * this->y,
			zSquared = this->z * this->z;

		return sqrt (xSquared + 
			ySquared + 
			zSquared);
	}

	double GetSqLength()
	{
		double xSquared = this->x * this->x,
			ySquared = this->y * this->y,
			zSquared = this->z * this->z;

		return xSquared + 
			ySquared + 
			zSquared;
	}

	void Normalize()
	{
		double vLength = this->GetLength();
		Vector3 ourVector = (*this);
		(*this) = ourVector / vLength;
	}

	void RotateInXZ (double angleInDegrees)
	{
		double alpha = angleInDegrees * PI/180;
		double resultZ = this->z * cos(alpha) - this->x * sin(alpha);
		double resultX = this->z * sin(alpha) + this->x * cos(alpha);
		this->z = resultZ;
		this->x = resultX;
	}
};

double DotProduct(Vector3 A, Vector3 B)
{
	return A.GetX() * B.GetX() + A.GetY() * B.GetY() + A.GetZ() * B.GetZ();
}

Vector3 CrossProduct(Vector3 A, Vector3 B)
{
	Vector3 result;
	result.SetX (A.GetY() * B.GetZ() - A.GetZ() * B.GetY());
	result.SetY (A.GetZ() * B.GetX() - A.GetX() * B.GetZ());
	result.SetZ (A.GetX() * B.GetY() - A.GetY() * B.GetX());

	return result;
}